﻿using System;
using System.Collections.Generic;
using System.Text;
using T.FAS.Runtime.DataAccess.SPI;
using T.FAS.Runtime.Metadata.Entity.DataModel;
using T.FAS.Runtime.DataAccess.SQLDom;
using T.FAS.Runtime.Base.Entity;
using T.FAS.Runtime.DataAccess.Common;
using System.Linq;

namespace T.FAS.Runtime.DataAccess.Engine
{
    /// <summary>
    /// CDO 默认SQL构造器
    /// </summary>
    class CDODefaultSQLBuilder: ICDOSQLBuilder
    {
        #region Save

        /// <summary>
        /// 解析生成Insert语句。
        /// </summary>       
        /// <param name="compositeDataObject">领域模型。</param>
        /// <param name="instance">要插入的数据。</param>        
        /// <returns>Insert语句集合。</returns>
        public SqlStatementCollection ParseInsertSql(CompositeDataObject compositeDataObject, TRecord instance, SqlExecuteControlContext controlContext = null)
        {
            var sqls = new SqlStatementCollection();
            
            var dataContext = DataContextBuilder.CreateDataContext<object>(compositeDataObject, compositeDataObject.RootCompositeNodeObject, DataAccessOpType.I, instance, controlContext);

            //解析SQL语句主干接口
            ParseInsertSqlSchema(sqls, compositeDataObject, compositeDataObject.RootCompositeNodeObject, controlContext);

            //在SqlSchema上逐表添加数据
            var result = ParseInsertSqlDetail(sqls, compositeDataObject, dataContext);
            if (result != null)
            {
                foreach (SqlStatement sql in result)
                {
                    sql.SqlBuildingInfo.MetaDataCode = compositeDataObject.Code ?? compositeDataObject.MetaDataCode;
                }
            }
            return result;
        }

        /// <summary>
        /// 解析生成指定领域对象的Insert语句。
        /// </summary>
        /// <param name="compositeDataObject">通用中间对象</param>
        /// <param name="compositeNodeObject">节点对象</param>
        /// <param name="instance">要插入的数据</param>        
        /// <returns>指定领域对象的Insert语句</returns>
        public SqlStatementCollection ParseInsertSql(CompositeDataObject compositeDataObject, CompositeNodeObject compositeNodeObject, TRecord instance, SqlExecuteControlContext controlContext = null)
        {
            var sqls = new SqlStatementCollection();
            var dataContext = DataContextBuilder.CreateDataContext<object>(compositeDataObject, compositeNodeObject, DataAccessOpType.I, instance, controlContext);

            //解析SQL语句主干接口
            ParseInsertSqlSchema(sqls, compositeDataObject, compositeNodeObject, controlContext);

            //在SqlSchema上逐表添加数据
            var result = ParseInsertSqlDetail(sqls, compositeDataObject, compositeNodeObject, dataContext);
            if (result != null)
            {
                foreach (SqlStatement sql in result)
                {
                    sql.SqlBuildingInfo.MetaDataCode = compositeDataObject.Code ?? compositeDataObject.MetaDataCode;
                }
            }
            return result;
        }


        /// <summary>
        /// 解析生成Insert语句的主干部分。
        /// </summary>
        /// <param name="sqlSchemata">Insert语句的主干。</param>
        /// <param name="co">通用中间对象。</param>
        /// <param name="node">通用中间对象的节点。</param>
        /// <returns>Insert语句的主干部分。</returns>
        private void ParseInsertSqlSchema(SqlStatementCollection sqlSchemata, CompositeDataObject CompositeDataObject, CompositeNodeObject CompositeNodeObject, SqlExecuteControlContext controlContext = null)
        {
            var insertStrategy = new InsertSqlBuildStrategy();
            var context = new SqlBuildingContext(CompositeDataObject, CompositeNodeObject, EnumTools.Convert<DatabaseType>(CompositeNodeObject.DataObject.Database.DbType), controlContext);            

            var nodeSqlSchemata = insertStrategy.BuildTableSqlSchema(context);
            sqlSchemata.AddRange(nodeSqlSchemata);

            //递归处理子对象
            if (context.Node.ChildCompositeNodeObjects.Count == 0) return;

            foreach (var childModelObject in context.Node.ChildCompositeNodeObjects)
            {
                ParseInsertSqlSchema(sqlSchemata, CompositeDataObject, childModelObject, controlContext);
            }
        }

        /// <summary>
        /// 根据已经解析的SqlSchema，解析生成带数据的Insert语句。
        /// </summary>
        /// <param name="sqlSchemata">已经解析的SqlSchema。</param>
        /// <param name="CompositeDataObject">领域对象</param>
        /// <param name="context">数据上下文</param>
        /// <returns>Insert语句集合</returns>
        private SqlStatementCollection ParseInsertSqlDetail(SqlStatementCollection sqlSchemata, CompositeDataObject CompositeDataObject, DataContext context)
        {
            var result = new SqlStatementCollection();

            foreach (var node in CompositeDataObject.CompositeNodeObjects)
            {
                if (!context.Data.Keys.Contains(node.ID))
                    continue;
                var data = context.Data[node.ID];
                if (data == null || data.Count == 0) continue;

                context.ResetCurrentDataIndex();
                var nodeSqls = ParseInsertSqlDetail(sqlSchemata, CompositeDataObject, node, context);
                result.AddRange(nodeSqls);
            }

            return result;
        }

        /// <summary>
        /// 根据已经解析的SqlSchema，解析生成带数据的Insert语句。
        /// </summary>
        /// <param name="sqlSchemata">已经解析的SqlSchema。</param>
        /// <param name="cdo">领域对象</param>
        /// <param name="cno">领域对象</param>
        /// <param name="dataContext">数据上下文</param>
        /// <returns>Insert语句集合</returns>
        private SqlStatementCollection ParseInsertSqlDetail(SqlStatementCollection sqlSchemata, CompositeDataObject cdo, CompositeNodeObject cno, DataContext dataContext)
        {
            var result = new SqlStatementCollection();
            var data = dataContext.Data[cno.ID];

            if (data == null || data.Count == 0) return result;

            var strategy = new InsertSqlBuildStrategy();

            for (int i = 0; i < dataContext.Data[cno.ID].Count; i++)
            {
                dataContext.CurrentDataIndex = i;
                var context = new SqlBuildingContext(cdo, cno, EnumTools.Convert<DatabaseType>(cno.DataObject.Database.DbType), dataContext);                

                var rowSqls = new SqlStatementCollection();
                var sqls = sqlSchemata.Where(s => s.SqlBuildingInfo.CurrentNode.ID == cno.ID).ToList();
                rowSqls.AddRangeClone(sqls);

                strategy.BuildTableSqlDetail(rowSqls, context);
                result.AddRange(rowSqls);
            }

            return result;
        }
        #endregion

        #region Query

        /// <summary>
        /// 解析生成查询SQL
        /// </summary>
        /// <remarks>按主键数据作为查询依据</remarks>
        /// <param name="compositeDataObject">领域模型</param>        
        /// <param name="dataID">主键数据</param>        
        /// <returns>查询SQL</returns>
        public SqlStatementCollection ParseQuerySqlByID(CompositeDataObject compositeDataObject, string dataID, SqlExecuteControlContext controlContext = null)
        {
            var sqls = new SqlStatementCollection();
            var sqlSchema = new SqlStatementCollection();
            
            var dataIDDic = CreatePkDataDictionary(compositeDataObject, compositeDataObject.RootCompositeNodeObject, dataID);
            DataContext dataContext = DataContextBuilder.CreateDataContext<IDictionary<string, object>>(compositeDataObject, compositeDataObject.RootCompositeNodeObject, DataAccessOpType.Q, dataIDDic);

            //解析SQL语句主干接口
            ParseQuerySqlSchema(sqlSchema, compositeDataObject, compositeDataObject.RootCompositeNodeObject, dataContext, controlContext);

            //在SqlSchema上逐表添加数据
            ParseQuerySqlDetail(sqlSchema, sqls, compositeDataObject, compositeDataObject.RootCompositeNodeObject, dataContext);

            if (sqls != null)
            {
                foreach (SqlStatement sql in sqls)
                {
                    sql.SqlBuildingInfo.MetaDataCode = compositeDataObject.Code ?? compositeDataObject.MetaDataCode;
                }
            }
            return sqls;
        }

        /// <summary>
        /// 解析生成查询SQL
        /// </summary>
        /// <remarks>按主键数据作为查询依据</remarks>
        /// <param name="compositeDataObject">领域模型</param>            
        /// <param name="compositeNodeObject">领域对象</param>        
        /// <param name="dataID">主键数据</param>        
        /// <returns>查询SQL</returns>
        public SqlStatementCollection ParseQuerySqlByID(CompositeDataObject compositeDataObject, CompositeNodeObject compositeNodeObject, string dataID, SqlExecuteControlContext controlContext = null)
        {
            var sqls = new SqlStatementCollection();
            var sqlSchema = new SqlStatementCollection();

            var dataIDDic = CreatePkDataDictionary(compositeDataObject, compositeNodeObject, dataID);
            var dataContext = DataContextBuilder.CreateDataContext<IDictionary<string, object>>(compositeDataObject, compositeNodeObject, DataAccessOpType.Q, dataIDDic);

            //解析SQL语句主干接口
            ParseQuerySqlSchema(sqlSchema, compositeDataObject, compositeNodeObject, dataContext, controlContext);

            //在SqlSchema上逐表添加数据
            ParseQuerySqlDetail(sqlSchema, sqls, compositeDataObject, compositeNodeObject, dataContext);

            if (sqls != null)
            {
                foreach (SqlStatement sql in sqls)
                {
                    sql.SqlBuildingInfo.MetaDataCode = compositeDataObject.Code ?? compositeDataObject.MetaDataCode;
                }
            }
            return sqls;
        }

        /// <summary>
        /// 解析生成查询SQL
        /// </summary>
        /// <param name="compositeDataObject">领域模型</param>        
        /// <param name="filter">过滤器</param>
        /// <returns>查询SQL</returns>
        [Obsolete]
        public SqlStatementCollection ParseQuerySqlByFilter(CompositeDataObject compositeDataObject, QueryFilter filter, SqlExecuteControlContext controlContext = null)
        {
            return ParseQuerySqlByFilter(compositeDataObject, compositeDataObject.RootCompositeNodeObject, filter);
        }

        /// <summary>
        /// 解析生成查询SQL
        /// </summary>
        /// <remarks>按主键数据作为查询依据</remarks>
        /// <param name="compositeDataObject">领域模型</param>            
        /// <param name="CompositeNodeObject">领域对象</param>               
        /// <param name="filter">过滤器</param>
        /// <returns>查询SQL</returns>
        [Obsolete]
        public SqlStatementCollection ParseQuerySqlByFilter(CompositeDataObject compositeDataObject, CompositeNodeObject CompositeNodeObject, QueryFilter filter, SqlExecuteControlContext controlContext = null)
        {
            var sqls = new SqlStatementCollection();
            var sqlSchema = new SqlStatementCollection();

            var dataContext = DataContextBuilder.CreateDataContext<QueryFilter>(compositeDataObject, CompositeNodeObject, DataAccessOpType.Q, filter);

            //解析SQL语句主干接口
            ParseQuerySqlSchema(sqlSchema, compositeDataObject, CompositeNodeObject, dataContext, controlContext);

            //在SqlSchema上逐表添加数据
            ParseQuerySqlDetail(sqlSchema, sqls, compositeDataObject, CompositeNodeObject, dataContext);

            return sqls;
        }

        private void ParseQuerySqlDetail(SqlStatementCollection sqlSchemata, SqlStatementCollection result, CompositeDataObject CompositeDataObject,
           CompositeNodeObject CompositeNodeObject, DataContext dataContext)
        {
            //构造SQL语句的条件
            var strategy = new SelectSqlBuildStrategy();
            var context = new SqlBuildingContext(CompositeDataObject, CompositeNodeObject, EnumTools.Convert<DatabaseType>(CompositeNodeObject.DataObject.Database.DbType), dataContext);
            var rowSqls = new SqlStatementCollection();
            var sqls = sqlSchemata.Where(s => s.SqlBuildingInfo.CurrentNode.ID == CompositeNodeObject.ID).ToList();
            rowSqls.AddRangeClone(sqls);
            strategy.BuildTableSqlDetail(rowSqls, context);
            result.AddRange(rowSqls);

            //递归处理子对象
            if (CompositeNodeObject.ChildCompositeNodeObjects.Count == 0 ||
                (dataContext.QueryFilter != null &&
                dataContext.QueryFilter.PageParameter != null && dataContext.QueryFilter.PageParameter.PageSize > 0)) return;

            foreach (var childModelObject in CompositeNodeObject.ChildCompositeNodeObjects)
            {
                ParseQuerySqlDetail(sqlSchemata, result, CompositeDataObject, childModelObject, dataContext);
            }
        }

        /// <summary>
        /// 构造查询SQL语句的主干结构
        /// </summary>
        /// <param name="dataObject">数据对象</param>
        /// <returns>查询SQL语句的主干结构</returns>
        private void ParseQuerySqlSchema(SqlStatementCollection sqlSchemata, CompositeDataObject CompositeDataObject, CompositeNodeObject CompositeNodeObject, DataContext dataContext, SqlExecuteControlContext controlContext)
        {
            SelectSqlBuildStrategy selectStrategy = new SelectSqlBuildStrategy();
            var context = new SqlBuildingContext(CompositeDataObject, CompositeNodeObject, EnumTools.Convert<DatabaseType>(CompositeNodeObject.DataObject.Database.DbType), dataContext);
            context.ControlContext = controlContext;
            var nodeSqlSchemata = selectStrategy.BuildTableSqlSchema(context);
            sqlSchemata.AddRange(nodeSqlSchemata);

            //非根节点查询不需要处理子对象
            if (CompositeNodeObject.ChildCompositeNodeObjects.Count == 0 || dataContext.MainCompositeNodeObject.IsRootObject == false ||
                (dataContext.QueryFilter != null &&
                dataContext.QueryFilter.PageParameter != null && dataContext.QueryFilter.PageParameter.PageSize > 0))
                return;

            //递归处理子对象
            foreach (var childModelObject in CompositeNodeObject.ChildCompositeNodeObjects)
            {
                ParseQuerySqlSchema(sqlSchemata, CompositeDataObject, childModelObject, dataContext, controlContext);
            }
        }

        /// <summary>
        /// 创建主键列删除条件
        /// </summary>
        /// <param name="CompositeDataObject"></param>
        /// <param name="CompositeNodeObject"></param>
        /// <param name="dataID"></param>
        /// <returns></returns>
        private Dictionary<string, object> CreatePkDataDictionary(CompositeDataObject CompositeDataObject, CompositeNodeObject CompositeNodeObject, string dataID)
        {
            var dataIDDic = new Dictionary<string, object>();
            foreach (var column in CompositeNodeObject.DataObject.PKColumns)
            {
                var pkElement = CompositeNodeObject.Elements.FirstOrDefault(i => i.DataColumnID == column.ID);
                dataIDDic.Add(pkElement.ID, dataID);
                break;
            }
            return dataIDDic;
        }
        #endregion

        #region Delete

        /// <summary>
        /// 解析生成删除SQL
        /// </summary>
        /// <remarks>按主键数据作为查询依据</remarks>
        /// <param name="compositeDataObject">领域模型</param>        
        /// <param name="dataID">主键数据</param>        
        /// <returns>删除SQL</returns>
        public SqlStatementCollection ParseDeleteSqlByID(CompositeDataObject compositeDataObject, string dataID, SqlExecuteControlContext context = null)
        {
            var sqls = new SqlStatementCollection();
            var sqlSchema = new SqlStatementCollection();
            
            var dataIDDic = CreatePkDataDictionary(compositeDataObject, compositeDataObject.RootCompositeNodeObject, dataID);
            var dataContext = DataContextBuilder.CreateDataContext<IDictionary<string, object>>(compositeDataObject, compositeDataObject.RootCompositeNodeObject, DataAccessOpType.D, dataIDDic);
            dataContext.EntryCompositeNodeObject = compositeDataObject.RootCompositeNodeObject; //保存调用节点入口            

            //解析SQL语句主干接口
            ParseDeleteSqlSchema(sqlSchema, compositeDataObject, compositeDataObject.RootCompositeNodeObject, dataContext);

            //在SqlSchema上逐表添加数据
            ParseDeleteSqlDetail(sqlSchema, sqls, compositeDataObject, compositeDataObject.RootCompositeNodeObject, dataContext);

            var result = new SqlStatementCollection();
            var reverseObjects = compositeDataObject.ReverseCompositeNodeObjects();
            if (reverseObjects == null || reverseObjects.Count <= 0)
            {
                result.AddRange(sqls);
            }
            else
            {
                foreach (var CompositeNodeObject in reverseObjects)
                {
                    var sql = sqls.FirstOrDefault(i => i.NodeID == CompositeNodeObject.ID);
                    if (sql != null)
                    {
                        result.Add(sql);
                    }
                }
            }
            if (result != null)
            {
                foreach (SqlStatement sql in result)
                {
                    sql.SqlBuildingInfo.MetaDataCode = compositeDataObject.Code ?? compositeDataObject.MetaDataCode;
                }
            }
            return result;
        }

        /// <summary>
        /// 解析生成删除SQL
        /// </summary>
        /// <remarks>按主键数据作为查询依据</remarks>
        /// <param name="compositeDataObject">领域模型</param> 
        /// <param name="compositeNodeObject">领域对象</param>
        /// <param name="dataID">主键数据</param>        
        /// <returns>删除SQL</returns>
        public SqlStatementCollection ParseDeleteSqlByID(CompositeDataObject compositeDataObject, CompositeNodeObject compositeNodeObject, string dataID, SqlExecuteControlContext context = null)
        {
            var sqls = new SqlStatementCollection();
            var sqlSchema = new SqlStatementCollection();
            
            //这里指定CompositeNodeObject节点时不能指定RootCompositeNodeObject
            var dataIDDic = CreatePkDataDictionary(compositeDataObject, compositeNodeObject, dataID);
            var dataContext = DataContextBuilder.CreateDataContext<IDictionary<string, object>>(compositeDataObject, compositeNodeObject, DataAccessOpType.D, dataIDDic);
            dataContext.EntryCompositeNodeObject = compositeNodeObject; //保存调用节点入口            

            //解析SQL语句主干接口
            ParseDeleteSqlSchema(sqlSchema, compositeDataObject, compositeNodeObject, dataContext);

            //在SqlSchema上逐表添加数据
            ParseDeleteSqlDetail(sqlSchema, sqls, compositeDataObject, compositeNodeObject, dataContext);

            var result = new SqlStatementCollection();
            var reverseObjects = compositeDataObject.ReverseCompositeNodeObjects();
            foreach (var tempCompositeNodeObject in reverseObjects)
            {
                var sql = sqls.FirstOrDefault(i => i.NodeID == tempCompositeNodeObject.ID);
                if (sql != null)
                {
                    result.Add(sql);
                }
            }
            if (result != null)
            {
                foreach (SqlStatement sql in result)
                {
                    sql.SqlBuildingInfo.MetaDataCode = compositeDataObject.Code ?? compositeDataObject.MetaDataCode;
                }
            }
            return result;
        }

        /// <summary>
        /// 构造查询SQL语句的主干结构
        /// </summary>
        /// <param name="dataObject">数据对象</param>
        /// <returns>查询SQL语句的主干结构</returns>
        private void ParseDeleteSqlSchema(SqlStatementCollection sqlSchemata, CompositeDataObject compositeDataObject, CompositeNodeObject compositeNodeObject, DataContext dataContext, SqlExecuteControlContext controlContext = null)
        {
            var selectStrategy = new DeleteSqlBuildStrategy();
            var context = new SqlBuildingContext(compositeDataObject, compositeNodeObject, EnumTools.Convert<DatabaseType>(compositeNodeObject.DataObject.Database.DbType), dataContext, controlContext);

            var nodeSqlSchemata = selectStrategy.BuildTableSqlSchema(context);
            sqlSchemata.AddRange(nodeSqlSchemata);

            //递归处理子对象
            if (compositeNodeObject.ChildCompositeNodeObjects.Count == 0) return;

            foreach (var childModelObject in compositeNodeObject.ChildCompositeNodeObjects)
            {
                ParseDeleteSqlSchema(sqlSchemata, compositeDataObject, childModelObject, dataContext);
            }
        }

        private void ParseDeleteSqlDetail(SqlStatementCollection sqlSchemata, SqlStatementCollection result, CompositeDataObject CompositeDataObject,
            CompositeNodeObject CompositeNodeObject, DataContext dataContext)
        {
            //构造SQL语句的条件
            var strategy = new DeleteSqlBuildStrategy();
            var context = new SqlBuildingContext(CompositeDataObject, CompositeNodeObject, EnumTools.Convert<DatabaseType>(CompositeNodeObject.DataObject.Database.DbType), dataContext);
            
            var rowSqls = new SqlStatementCollection();
            var sqls = sqlSchemata.Where(s => s.SqlBuildingInfo.CurrentNode.ID == CompositeNodeObject.ID).ToList();
            rowSqls.AddRangeClone(sqls);
            strategy.BuildTableSqlDetail(rowSqls, context);
            result.AddRange(rowSqls);

            //递归处理子对象
            if (CompositeNodeObject.ChildCompositeNodeObjects.Count == 0) return;
            foreach (var childModelObject in CompositeNodeObject.ChildCompositeNodeObjects)
            {
                ParseDeleteSqlDetail(sqlSchemata, result, CompositeDataObject, childModelObject, dataContext);
            }
        }

        #endregion

        #region Update

        /// <summary>
        /// 解析生成Update语句。
        /// </summary>       
        /// <param name="compositeDataObject">领域模型。</param>
        /// <param name="instance">要更新的数据。</param>        
        /// <returns>Update语句集合。</returns>
        public SqlStatementCollection ParseUpdateSql(CompositeDataObject compositeDataObject, TRecord instance, SqlExecuteControlContext controlContext = null)
        {
            var updateContext = DataContextBuilder.CreateDataContextForUpdate<object>(compositeDataObject, compositeDataObject.RootCompositeNodeObject, instance, controlContext);
            var result = ParseUpdateSql(compositeDataObject, updateContext, controlContext);
            if (result != null)
            {
                foreach (SqlStatement sql in result)
                {
                    sql.SqlBuildingInfo.MetaDataCode = compositeDataObject.Code ?? compositeDataObject.MetaDataCode;
                }
            }
            return result;
        }

        /// <summary>
        /// 解析生成Update语句。
        /// </summary>       
        /// <param name="compositeDataObject">领域模型。</param>
        /// <param name="instance">要更新的数据。</param>        
        /// <returns>Update语句集合。</returns>
        public SqlStatementCollection ParseUpdateSql(CompositeDataObject compositeDataObject, CompositeNodeObject momainObject, TRecord instance, SqlExecuteControlContext controlContext = null)
        {
            var updateContext = DataContextBuilder.CreateDataContextForUpdate<object>(compositeDataObject, momainObject, instance, controlContext);
            var result = ParseUpdateSql(compositeDataObject, updateContext);
            if (result != null)
            {
                foreach (SqlStatement sql in result)
                {
                    sql.SqlBuildingInfo.MetaDataCode = compositeDataObject.Code ?? compositeDataObject.MetaDataCode;
                }
            }
            return result;
        }

        /// <summary>
        /// 处理Update语句
        /// </summary>
        /// <param name="CompositeDataObject"></param>
        /// <param name="updateContext"></param>
        /// <returns></returns>
        private SqlStatementCollection ParseUpdateSql(CompositeDataObject CompositeDataObject, UpdateDataContext updateContext, SqlExecuteControlContext controlContext = null)
        {
            var sqls = new SqlStatementCollection();
            var deleteSqls = new SqlStatementCollection();
            var insertSqls = new SqlStatementCollection();
            var updateSqls = new SqlStatementCollection();

            // 处理子节点的Delete语句
            if (updateContext.DeleteContext != null && updateContext.DeleteContext.Count > 0)
            {
                foreach (var context in updateContext.DeleteContext)
                {
                    deleteSqls.AddRange(DealWithChildNodeDel(CompositeDataObject, context, controlContext));
                }
            }
            // 处理子节点Insert语句
            insertSqls.AddRange(DealWithChildNodeInsert(CompositeDataObject, updateContext.InsertContext, controlContext));
            // 处理子节点Update语句
            updateSqls.AddRange(DealWithChildNodeUpdate(CompositeDataObject, updateContext.UpdateContext, controlContext));

            //编排执行顺序，子节点删除->子节点插入->主节点更新
            sqls.AddRange(deleteSqls);
            sqls.AddRange(insertSqls);
            sqls.AddRange(updateSqls);
            return sqls;
        }

        /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^修改操作代码重构^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/

        /// <summary>
        /// 解析生成Insert语句的主干部分。
        /// </summary>
        /// <param name="sqlSchemata">Insert语句的主干。</param>
        /// <param name="co">通用中间对象。</param>
        /// <param name="node">通用中间对象的节点。</param>
        /// <returns>Insert语句的主干部分。</returns>
        private void ParseUpdateSqlSchema(SqlStatementCollection sqlSchemata, CompositeDataObject CompositeDataObject, CompositeNodeObject CompositeNodeObject, DataContext dataContext, SqlExecuteControlContext controlContext = null)
        {
            var updateStrategy = new UpdateSqlBuildStrategy();
            var context = new SqlBuildingContext(CompositeDataObject, CompositeNodeObject, EnumTools.Convert<DatabaseType>(CompositeNodeObject.DataObject.Database.DbType), controlContext);
            
            if (dataContext.GetCurrentDataContextItem(CompositeNodeObject.ID) != null)
            {
                var nodeSqlSchemata = updateStrategy.BuildTableSqlSchema(context);
                sqlSchemata.AddRange(nodeSqlSchemata);
            }

            //递归处理子对象
            if (context.Node.ChildCompositeNodeObjects.Count == 0) return;

            foreach (var childModelObject in context.Node.ChildCompositeNodeObjects)
            {
                ParseUpdateSqlSchema(sqlSchemata, CompositeDataObject, childModelObject, dataContext, controlContext);
            }
        }

        /// <summary>
        /// 根据已经解析的SqlSchema，解析生成带数据的Update语句。
        /// </summary>
        /// <param name="sqlSchemata">已经解析的SqlSchema。</param>
        /// <param name="CompositeDataObject">领域对象</param>
        /// <param name="context">数据上下文</param>
        /// <returns>Insert语句集合</returns>
        private SqlStatementCollection ParseUpdateSqlDetail(SqlStatementCollection sqlSchemata, CompositeDataObject CompositeDataObject, DataContext context)
        {
            var result = new SqlStatementCollection();

            foreach (var node in CompositeDataObject.CompositeNodeObjects)
            {
                if (!context.Data.Keys.Contains(node.ID))
                    continue;
                var data = context.Data[node.ID];
                if (data == null || data.Count == 0) continue;

                context.ResetCurrentDataIndex();
                var nodeSqls = ParseUpdateSqlDetail(sqlSchemata, CompositeDataObject, node, context);
                result.AddRange(nodeSqls);
            }

            return result;
        }

        /// <summary>
        /// 根据已经解析的SqlSchema，解析生成带数据的Update语句。
        /// </summary>
        /// <param name="sqlSchemata">已经解析的SqlSchema。</param>
        /// <param name="CompositeDataObject">领域对象</param>
        /// <param name="context">数据上下文</param>
        /// <returns>Insert语句集合</returns>
        private SqlStatementCollection ParseUpdateSqlDetail(SqlStatementCollection sqlSchemata, CompositeDataObject CompositeDataObject, CompositeNodeObject CompositeNodeObject, DataContext dataContext)
        {
            var result = new SqlStatementCollection();
            if (!dataContext.Data.ContainsKey(CompositeNodeObject.ID))
            {
                return result;
            }
            var data = dataContext.Data[CompositeNodeObject.ID];

            if (data == null || data.Count == 0) return result;

            var strategy = new UpdateSqlBuildStrategy();

            for (int i = 0; i < dataContext.Data[CompositeNodeObject.ID].Count; i++)
            {
                dataContext.CurrentDataIndex = i;
                var context = new SqlBuildingContext(CompositeDataObject, CompositeNodeObject, EnumTools.Convert<DatabaseType>(CompositeNodeObject.DataObject.Database.DbType), dataContext);               

                var rowSqls = new SqlStatementCollection();
                var sqls = sqlSchemata.Where(s => s.SqlBuildingInfo.CurrentNode.ID == CompositeNodeObject.ID).ToList();
                rowSqls.AddRangeClone(sqls);

                strategy.BuildTableSqlDetail(rowSqls, context);
                result.AddRange(rowSqls);
            }

            return result;
        }

        #region Update内部方法
        /// <summary>
        /// 处理Update语句的节点删除语句
        /// </summary>
        /// <param name="CompositeDataObject"></param>
        /// <param name="dataContext"></param>
        /// <param name="controlContext"></param>
        /// <returns></returns>
        SqlStatementCollection DealWithChildNodeDel(CompositeDataObject CompositeDataObject, DataContext dataContext, SqlExecuteControlContext controlContext = null)
        {
            var sqls = new SqlStatementCollection();
            var sqlSchema = new SqlStatementCollection();
            //解析SQL语句主干接口
            ParseDeleteSqlSchema(sqlSchema, CompositeDataObject, dataContext.EntryCompositeNodeObject, dataContext, controlContext);

            //在SqlSchema上逐表添加数据
            ParseDeleteSqlDetail(sqlSchema, sqls, CompositeDataObject, dataContext.EntryCompositeNodeObject, dataContext);

            var result = new SqlStatementCollection();
            var reverseObjects = CompositeDataObject.ReverseCompositeNodeObjects();
            foreach (var tempCompositeNodeObject in reverseObjects)
            {
                var sql = sqls.FirstOrDefault(i => i.NodeID == tempCompositeNodeObject.ID);
                if (sql != null)
                {
                    result.Add(sql);
                }
            }
            return result;
        }

        /// <summary>
        /// 处理Update语句的节点插入语句
        /// </summary>
        /// <param name="CompositeDataObject"></param>
        /// <param name="dataContext"></param>
        /// <param name="controlContext"></param>
        /// <returns></returns>
        SqlStatementCollection DealWithChildNodeInsert(CompositeDataObject CompositeDataObject, DataContext dataContext, SqlExecuteControlContext controlContext = null)
        {
            var sqls = new SqlStatementCollection();
            //解析SQL语句主干接口
            ParseInsertSqlSchema(sqls, CompositeDataObject, CompositeDataObject.RootCompositeNodeObject, controlContext);
            //在SqlSchema上逐表添加数据
            return ParseInsertSqlDetail(sqls, CompositeDataObject, dataContext);
        }

        /// <summary>
        /// 处理Update语句的节点更新语句
        /// </summary>
        /// <param name="CompositeDataObject"></param>
        /// <param name="dataContext"></param>
        /// <param name="controlContext"></param>
        /// <returns></returns>
        SqlStatementCollection DealWithChildNodeUpdate(CompositeDataObject CompositeDataObject, DataContext dataContext, SqlExecuteControlContext controlContext = null)
        {
            var sqls = new SqlStatementCollection();

            //解析SQL语句主干接口
            ParseUpdateSqlSchema(sqls, CompositeDataObject, CompositeDataObject.RootCompositeNodeObject, dataContext, controlContext);

            //在SqlSchema上逐表添加数据
            return ParseUpdateSqlDetail(sqls, CompositeDataObject, dataContext);
        }

        #endregion
        #endregion

        #region 调试获取SQL用

        /// <summary>
        /// 解析生成Insert语句。
        /// </summary>       
        /// <param name="compositeDataObject">领域模型。</param>
        /// <returns>Insert语句集合。</returns>
        public SqlStatementCollection GetInsertSQLs(CompositeDataObject compositeDataObject, SqlExecuteControlContext controlContext = null)
        {
            var sqls = new SqlStatementCollection();
            //解析SQL语句主干接口
            ParseInsertSqlSchema(sqls, compositeDataObject, compositeDataObject.RootCompositeNodeObject, controlContext);
            return sqls;
        }

        /// <summary>
        /// 解析生成Update语句。
        /// </summary>       
        /// <param name="compositeDataObject">领域模型。</param>
        /// <param name="instance">要更新的数据。</param>        
        /// <returns>Update语句集合。</returns>
        public SqlStatementCollection GetUpdateSQLs(CompositeDataObject compositeDataObject, SqlExecuteControlContext controlContext = null)
        {
            var updateContext = DataContextBuilder.CreateDataContextForUpdate<object>(compositeDataObject, compositeDataObject.RootCompositeNodeObject, null, controlContext);
            var result = ParseUpdateSql(compositeDataObject,  updateContext, controlContext);
            if (result != null)
            {
                foreach (SqlStatement sql in result)
                {
                    sql.SqlBuildingInfo.MetaDataCode = compositeDataObject.Code ?? compositeDataObject.MetaDataCode;
                }
            }
            return result;
        }


        /// <summary>
        /// 解析生成查询SQL
        /// </summary>
        /// <remarks>按主键数据作为查询依据</remarks>
        /// <param name="compositeDataObject">领域模型</param>        
        /// <param name="dataID">主键数据</param>        
        /// <returns>查询SQL</returns>
        public SqlStatementCollection GetQueryByIdSQLs(CompositeDataObject compositeDataObject, string dataID, SqlExecuteControlContext controlContext = null)
        {
            var sqls = new SqlStatementCollection();
            var sqlSchema = new SqlStatementCollection();

            var dataIDDic = CreatePkDataDictionary(compositeDataObject, compositeDataObject.RootCompositeNodeObject, dataID);
            DataContext dataContext = DataContextBuilder.CreateDataContext<IDictionary<string, object>>(compositeDataObject, compositeDataObject.RootCompositeNodeObject, DataAccessOpType.Q, dataIDDic);

            //解析SQL语句主干接口
            ParseQuerySqlSchema(sqlSchema, compositeDataObject, compositeDataObject.RootCompositeNodeObject, dataContext, controlContext);

            //在SqlSchema上逐表添加数据
            ParseQuerySqlDetail(sqlSchema, sqls, compositeDataObject, compositeDataObject.RootCompositeNodeObject, dataContext);

            if (sqls != null)
            {
                foreach (SqlStatement sql in sqls)
                {
                    sql.SqlBuildingInfo.MetaDataCode = compositeDataObject.Code ?? compositeDataObject.MetaDataCode;
                }
            }
            return sqls;
        }

        /// <summary>
        /// 解析生成删除SQL
        /// </summary>
        /// <remarks>按主键数据作为查询依据</remarks>
        /// <param name="compositeDataObject">领域模型</param>        
        /// <param name="dataID">主键数据</param>        
        /// <returns>删除SQL</returns>
        public SqlStatementCollection GetDeleteByIdSQLs(CompositeDataObject compositeDataObject, string dataID, SqlExecuteControlContext context = null)
        {
            var sqls = new SqlStatementCollection();
            var sqlSchema = new SqlStatementCollection();

            var dataIDDic = CreatePkDataDictionary(compositeDataObject, compositeDataObject.RootCompositeNodeObject, dataID);
            var dataContext = DataContextBuilder.CreateDataContext<IDictionary<string, object>>(compositeDataObject, compositeDataObject.RootCompositeNodeObject, DataAccessOpType.D, dataIDDic);
            dataContext.EntryCompositeNodeObject = compositeDataObject.RootCompositeNodeObject; //保存调用节点入口            

            //解析SQL语句主干接口
            ParseDeleteSqlSchema(sqlSchema, compositeDataObject, compositeDataObject.RootCompositeNodeObject, dataContext);

            //在SqlSchema上逐表添加数据
            ParseDeleteSqlDetail(sqlSchema, sqls, compositeDataObject, compositeDataObject.RootCompositeNodeObject, dataContext);

            var result = new SqlStatementCollection();
            var reverseObjects = compositeDataObject.ReverseCompositeNodeObjects();
            if (reverseObjects == null || reverseObjects.Count <= 0)
            {
                result.AddRange(sqls);
            }
            else
            {
                foreach (var CompositeNodeObject in reverseObjects)
                {
                    var sql = sqls.FirstOrDefault(i => i.NodeID == CompositeNodeObject.ID);
                    if (sql != null)
                    {
                        result.Add(sql);
                    }
                }
            }
            if (result != null)
            {
                foreach (SqlStatement sql in result)
                {
                    sql.SqlBuildingInfo.MetaDataCode = compositeDataObject.Code ?? compositeDataObject.MetaDataCode;
                }
            }
            return result;
        }

        #endregion
    }
}
